package com.gold.config.client;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

@ConfigurationProperties("spring.cloud.config")
public class ConfigClientProperties
{
    public static final String PREFIX = "spring.cloud.config";
    public static final String TOKEN_HEADER = "X-Config-Token";
    public static final String STATE_HEADER = "X-Config-State";
    private boolean enabled = true;
    private String profile = "default";
    @Value("${spring.application.name:application}")
    private String name;
    private String label;
    private String username;
    private String password;
    private String uri = "http://localhost:8888";
    private Discovery discovery = new Discovery();
    private boolean failFast = false;
    private String token;
    private String authorization;
    private Map<String, String> headers = new HashMap();

    private ConfigClientProperties() {}

    public ConfigClientProperties(Environment environment)
    {
        String[] profiles = environment.getActiveProfiles();
        if (profiles.length == 0) {
            profiles = environment.getDefaultProfiles();
        }
        setProfile(StringUtils.arrayToCommaDelimitedString(profiles));
    }

    public boolean isEnabled()
    {
        return this.enabled;
    }

    public void setEnabled(boolean enabled)
    {
        this.enabled = enabled;
    }

    public String getRawUri()
    {
        return extractCredentials().uri;
    }

    public String getUri()
    {
        return this.uri;
    }

    public void setUri(String url)
    {
        this.uri = url;
    }

    public String getName()
    {
        return this.name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getProfile()
    {
        return this.profile;
    }

    public void setProfile(String env)
    {
        this.profile = env;
    }

    public String getLabel()
    {
        return this.label;
    }

    public void setLabel(String label)
    {
        this.label = label;
    }

    public String getUsername()
    {
        return extractCredentials().username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public String getPassword()
    {
        return extractCredentials().password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

    public Discovery getDiscovery()
    {
        return this.discovery;
    }

    public void setDiscovery(Discovery discovery)
    {
        this.discovery = discovery;
    }

    public boolean isFailFast()
    {
        return this.failFast;
    }

    public void setFailFast(boolean failFast)
    {
        this.failFast = failFast;
    }

    public String getToken()
    {
        return this.token;
    }

    public void setToken(String token)
    {
        this.token = token;
    }

    @DeprecatedConfigurationProperty(reason="replaced by headers", replacement="headers")
    @Deprecated
    public String getAuthorization()
    {
        return this.authorization;
    }

    public void setAuthorization(String authorization)
    {
        this.authorization = authorization;
    }

    public Map<String, String> getHeaders()
    {
        return this.headers;
    }

    public void setHeaders(Map<String, String> headers)
    {
        this.headers = headers;
    }

    private Credentials extractCredentials()
    {
        Credentials result = new Credentials();
        String uri = this.uri;
        result.uri = uri;
        Credentials explicitCredentials = getUsernamePassword();
        result.username = explicitCredentials.username;
        result.password = explicitCredentials.password;
        try
        {
            URL url = new URL(uri);
            String userInfo = url.getUserInfo();
            if ((StringUtils.isEmpty(userInfo)) || (":".equals(userInfo))) {
                return result;
            }
            String bare = UriComponentsBuilder.fromHttpUrl(uri).userInfo(null).build().toUriString();
            result.uri = bare;
            if (!userInfo.contains(":")) {
                userInfo = userInfo + ":";
            }
            String[] split = userInfo.split(":");

            result.username = split[0];
            result.password = split[1];
            if (explicitCredentials.password != null) {
                result.password = explicitCredentials.password;
            }
            if (!"user".equals(explicitCredentials.username)) {
                result.username = explicitCredentials.username;
            }
            return result;
        }
        catch (MalformedURLException e)
        {
            throw new IllegalStateException("Invalid URL: " + uri);
        }
    }

    private Credentials getUsernamePassword()
    {
        Credentials credentials = new Credentials();
        if (StringUtils.hasText(this.password)) {
            credentials.password = this.password.trim();
        }
        if (StringUtils.hasText(this.username)) {
            credentials.username = this.username.trim();
        } else {
            credentials.username = "user";
        }
        return credentials;
    }

    public static class Discovery
    {
        public static final String DEFAULT_CONFIG_SERVER = "configserver";
        private boolean enabled;
        private String serviceId = "configserver";

        public boolean isEnabled()
        {
            return this.enabled;
        }

        public void setEnabled(boolean enabled)
        {
            this.enabled = enabled;
        }

        public String getServiceId()
        {
            return this.serviceId;
        }

        public void setServiceId(String serviceId)
        {
            this.serviceId = serviceId;
        }
    }

    public ConfigClientProperties override(Environment environment)
    {
        ConfigClientProperties override = new ConfigClientProperties();
        BeanUtils.copyProperties(this, override);
        override.setName(environment
                .resolvePlaceholders("${spring.cloud.config.name:${spring.application.name:application}}"));
        if (environment.containsProperty("spring.cloud.config.profile")) {
            override.setProfile(environment
                    .getProperty("spring.cloud.config.profile"));
        }
        if (environment.containsProperty("spring.cloud.config.label")) {
            override.setLabel(environment
                    .getProperty("spring.cloud.config.label"));
        }
        return override;
    }

    public String toString()
    {
        return "ConfigClientProperties [enabled=" + this.enabled + ", profile=" + this.profile + ", name=" + this.name + ", label=" + (this.label == null ? "" : this.label) + ", username=" + this.username + ", password=" + this.password + ", uri=" + this.uri + ", authorization=" + this.authorization + ", discovery.enabled=" + this.discovery.enabled + ", failFast=" + this.failFast + ", token=" + this.token + "]";
    }

    private static class Credentials
    {
        private String username;
        private String password;
        private String uri;
    }
}